/*
**
**			Heroes IV
**	  Copyright 2001, The 3DO Company
**
**      town_prison_window.cpp
*/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "town_prison_window.h"

#include "adventure_frame.h"
#include "adventure_map.h"
#include "adaptor_handler.h"
#include "army_list_window.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_group_window.h"
#include "bitmap_layer_cache_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "creature.h"
#include "creature_traits.h"
#include "external_string.h"
#include "format_string.h"
#include "game_window.h"
#include "hero.h"
#include "interface_help.h"
#include "player.h"
#include "replace_keywords.h"
#include "scrollbar.h"
#include "simple_dialog.h"
#include "standard_fonts.h"
#include "town.h"
#include "town_properties.h"

extern t_external_string const k_text_class_level( "class_level.dialog" );
extern t_bitmap_group_cache     g_creature_rings;
extern t_button_cache			g_ok_button;
extern t_bitmap_group_cache     g_banners_38;

namespace 
{ // unnamed namespace

    t_external_string const k_text_prison_title( "town_prison_prison_title.misc" );
    t_external_string const k_text_no_prisoners( "town_prison_no_prisoners.misc" );
    
    t_bitmap_group_cache     k_prison_bitmaps ("dialog.prison");
    const   int k_max_num_portraits = 7;

};

t_town_prison_window::t_town_prison_window( t_town* town_ptr, t_adventure_frame* frame, t_window* parent_ptr )
                   : t_window( k_completely_transparent, parent_ptr )
{
	t_screen_rect           rect;
	t_bitmap_layer const*   layer;
	//t_window*               window_ptr;
	t_window*               background;
	t_screen_point          origin(0,0);
	t_text_window *         text_window_ptr;

    m_prisoners = town_ptr->get_prisoner_list();

    // Show dialog if there are no prisoners.
    if ( m_prisoners.size() == 0 )
    {
        ok_dialog ( k_text_no_prisoners );
        close();
        return;
    }

    m_adventure_frame = frame;
	m_bitmaps_ptr = k_prison_bitmaps.get();
	m_flags_bitmaps_ptr = g_banners_38.get();

    layer = m_bitmaps_ptr->find( "background" );
    background = new t_bitmap_layer_window( layer, origin, this );

    // Main prisoner portrait.
	rect = m_bitmaps_ptr->find( "hero_portrait" )->get_rect();
    m_main_portrait = new t_bitmap_layer_window( t_bitmap_layer_ptr(),
	                                rect.top_left(), this );

	rect = m_bitmaps_ptr->find( "hero_flag" )->get_rect();
    m_main_flag_ptr = new t_bitmap_layer_window( t_bitmap_layer_ptr(),
	                                rect.top_left(), this );

    // Use this just to get location.
	rect = m_flags_bitmaps_ptr->find( k_player_color_keyword[ k_player_red ] )->get_rect();
    m_main_alignment_ptr = new t_bitmap_layer_window( t_bitmap_layer_ptr(),
	                                rect.top_left(), m_main_flag_ptr );

	rect = m_bitmaps_ptr->find( "hero_name" )->get_rect();
	m_main_name_ptr  = new t_text_window( get_font( rect.height() ), rect, this, "", t_pixel_24(0,0,0) );
	m_main_name_ptr->set_center_horizontal();

	rect = m_bitmaps_ptr->find( "hero_class" )->get_rect();
	m_main_class_ptr  = new t_text_window( get_font( rect.height() ), rect, this, "", t_pixel_24(0,0,0) );
	m_main_class_ptr->set_center_horizontal();

	rect = m_bitmaps_ptr->find( "hero_level" )->get_rect();
	m_main_level_ptr  = new t_text_window( get_font( rect.height() ), rect, this, "", t_pixel_24(0,0,0) );
	m_main_level_ptr->set_center_horizontal();

    // Text.
	rect = m_bitmaps_ptr->find( "title" )->get_rect();
	text_window_ptr  = new t_text_window( get_font( rect.height() ), rect, this, k_text_prison_title, t_pixel_24(0,0,0) );
	text_window_ptr->set_center_horizontal();
    
    int num_portraits = m_prisoners.size();
    if (num_portraits > k_max_num_portraits)
        num_portraits = k_max_num_portraits;

    // Create frames.
	rect = m_bitmaps_ptr->find( "imprisoned_heroes" )->get_rect();
	create_frames( rect.top_left(), num_portraits, this );

    // Scrollbar.
    int scrollbar_limit = 0;
    if ( m_prisoners.size() > k_max_num_portraits )
    {
        scrollbar_limit = m_prisoners.size() - k_max_num_portraits;

    	rect = m_bitmaps_ptr->find( "scrollbar" )->get_rect();
    	m_scrollbar = new t_scrollbar( rect.top_left(), rect.height(), this, 0, 0, true );
    	m_scrollbar->set_position( 0 );
    	m_scrollbar->set_handler( bound_handler( *this, &t_town_prison_window::scrollbar_move));
    	m_scrollbar->set_limits( 0, scrollbar_limit );
    }

    m_prisoner_index = 0;
    update_frames( 0 );
    set_highlight( 0 );

    /*
    ** Create buttons.
    */
	t_button            *button_ptr;

	// Create close button
	t_help_block const&	    shared_help = get_help_block( "shared" );
	rect = m_bitmaps_ptr->find( "Close_Button" )->get_rect();
	button_ptr = new t_button( g_ok_button.get(), rect.top_left(), background );
	button_ptr->set_click_handler( bound_handler( *this, &t_town_prison_window::close_click ));
  set_help( button_ptr, shared_help, "ok" );
    
    // Center the position and display the window.
    t_screen_rect parent_rect = get_parent()->get_client_rect();
    rect = m_bitmaps_ptr->get_rect();
    rect += (parent_rect.size() - rect.size()) / 2;
    init( rect );
}

/*
** Create hero/prisoner frames.
*/
void t_town_prison_window::create_frames( t_screen_point const& origin, int num_frames, t_window* parent )
{
	t_bitmap_group_ptr bitmap_rings = g_creature_rings.get();

	// create portraits / buttons
	int             i;
    int             index;
	t_screen_point  point;
	t_screen_point  portrait_point;
	t_button*       button_ptr;

    // Don't need top & bottom for this one...
	static char const* k_names[3] = 
	{
		"vertical_top", "vertical_middle", "vertical_bottom"
	};

	t_bitmap_layer const* layer[3];
	t_bitmap_layer const* highlight[3];
	std::string           layer_name;

	// Load layers from border file.
	for (i = 0; i<3; i++)
	{
		layer_name = k_names[i];
		layer[i] = bitmap_rings->find( layer_name );
		layer_name += "_highlight" ;
		highlight[i] = bitmap_rings->find( layer_name );
	}

	// find the offset of the portrait relative to the border
	t_screen_rect           portrait_rect = bitmap_rings->find( "portrait" )->get_rect();
	t_screen_point          portrait_offset = portrait_rect.top_left();
	t_screen_point          border_offset;
	t_bitmap_layer const*   border;
	t_bitmap_layer const*   flag_layer;
	//t_window *              window_ptr;

    // Portrait frames.
	t_bitmap_layer_window * portrait_window;
	t_bitmap_layer_window * portrait_border;

	point = origin;

	for (i = 0; i < num_frames; i++)
	{
        // Beginning.
        if (i == 0)
    		index = 0;
        // End.
        else if (i == (num_frames-1))
    		index = 2;
        else
    		index = 1;

		border = layer[index];

		// make upper left corner of border == point
		border_offset = -border->get_rect().top_left();

        portrait_point = point + portrait_rect.top_left() + border_offset;

	    button_ptr = new t_button( portrait_point, this );
		portrait_window = new t_bitmap_layer_window( t_bitmap_layer_ptr(),
	                                t_screen_point( 0, 0 ), button_ptr );
	    button_ptr->set_released_image( portrait_window );
        button_ptr->set_click_handler( add_2nd_argument( bound_handler( *this, &t_town_prison_window::portrait_clicked ), i ));
	    button_ptr->enable( true );
        button_ptr->update_size();

        m_portrait_window_list.push_back ( portrait_window );
        
		// create border
		portrait_border = new t_bitmap_layer_window( border, point + border_offset, this );
        m_portrait_border_list.push_back( portrait_border );

		border = highlight[index];
		portrait_border = new t_bitmap_layer_window( border, point + border_offset, this );
	    m_portrait_highlight_border_list.push_back( portrait_border );

		point.y += border->get_height();
	}

    // Hero/alignment flags.
    t_hero*             hero_ptr;
	t_player_color      player_color;
    int                 player_num;
	t_window *          flag_window_ptr;
	t_window *          window_ptr;
	//t_town_type         alignment;
	//t_bitmap_layer *    alignment_layer;
    //t_window *          alignment_window_ptr;
    t_adventure_map*    map_ptr = m_adventure_frame->get_map();
	t_screen_rect       flag_rect = m_bitmaps_ptr->find( "hero_1_flag" )->get_rect();
    
	for (i = 0; i < m_prisoners.size(); i++)
	{
        hero_ptr = m_prisoners[ i ].hero;

        window_ptr = new t_window ( flag_rect, k_completely_transparent, this );

        // Get correct flag.
        player_num = m_prisoners[ i ].owner_number;
        t_player & player = map_ptr->get_player( player_num );
	    player_color = player.get_color();
		
        flag_layer = m_flags_bitmaps_ptr->find( k_player_color_keyword[ player_color ] );
        flag_window_ptr = new t_bitmap_layer_window( flag_layer, t_screen_point( 0, 0 ), window_ptr );
        
        // Alignment.
        //alignment = player.get_alignment();
        //alignment_layer = m_flags_bitmaps_ptr->find( get_alignment_keyword( alignment ) );
        //alignment_window_ptr = new t_bitmap_layer_window( alignment_layer, t_screen_point( 0, 0 ), flag_window_ptr );
	    
        m_portrait_flag_list.push_back( window_ptr );
    }
}

void t_town_prison_window::update_frames( int starting_index )
{
    //if (starting_index > m_portrait_window_list.size())
    //    return;
    
    int                 i;
    t_hero *            hero_ptr;
    t_screen_point      point;
    t_adventure_map*    map_ptr = m_adventure_frame->get_map();
    int prisoner_index = starting_index;

	for (i = 0; i<m_portrait_flag_list.size(); i++)
    {
        m_portrait_flag_list[ i ]->set_visible( false );
    }

    m_frame_index = starting_index;
	for (i = 0; i<m_portrait_window_list.size(); i++)
    {
        hero_ptr = m_prisoners[prisoner_index].hero;

        // Portrait.
		m_portrait_window_list[i]->set_bitmap( hero_ptr->get_portrait() );
		m_portrait_window_list[i]->set_help_balloon_text( hero_ptr->get_name() );

        // Show correct flag.
	    std::string     flag_name = format_string( "hero_%i_flag", i + 1 );
    	point = m_bitmaps_ptr->find( flag_name )->get_rect().top_left();
        
        m_portrait_flag_list[ prisoner_index ]->move( point );
        m_portrait_flag_list[ prisoner_index ]->set_visible( true );

        prisoner_index++;
    }
}

// Set frame highlight.
void t_town_prison_window::set_highlight( int index )
{
    t_hero * hero_ptr;
    int     i;

    if (m_prisoners.size() == 0)
        return;

    m_cur_window_index = index;

	for (i = 0; i<m_portrait_window_list.size(); i++)
    {
	    m_portrait_highlight_border_list[i]->set_visible( false );
        m_portrait_border_list[i]->set_visible( true );
    }

    m_portrait_highlight_border_list[ index ]->set_visible( true );
    m_portrait_border_list[ index ]->set_visible( false );

    // Prisoner portrait.
    hero_ptr = m_prisoners[ m_prisoner_index ].hero;
	m_main_portrait->set_bitmap( hero_ptr->get_portrait( 82 ) );
	m_main_name_ptr->set_text( hero_ptr->get_name() );
    m_main_class_ptr->set_text( hero_ptr->get_class_name() );
	m_main_class_ptr->set_right_click_text( hero_ptr->get_class_description() );
	m_main_level_ptr->set_text( replace_keywords( k_text_class_level, "%level", format_string("%i", hero_ptr->get_level()) ));
    
    // Flag.
    t_adventure_map* map_ptr = m_adventure_frame->get_map();
    int player_num = m_prisoners[m_prisoner_index].owner_number;
    t_player & player = map_ptr->get_player( player_num );
	t_player_color  player_color = player.get_color();

	m_main_flag_ptr->set_bitmap( m_flags_bitmaps_ptr->find( k_player_color_keyword[ player_color ] ) );
    
    //t_town_type     alignment = player.get_alignment();
	//m_main_alignment_ptr->set_bitmap( m_flags_bitmaps_ptr->find( get_alignment_keyword( alignment ) ) );
}

void t_town_prison_window::portrait_clicked( t_button *button_ptr, int index )
{
    m_prisoner_index = m_frame_index + index;
    t_town_prison_window::set_highlight( index );
}

void t_town_prison_window::scrollbar_move( t_scrollbar* scrollbar, int value )
{
    update_frames( value );
    portrait_clicked( NULL, m_cur_window_index );
}

/*
** Clicked close button.
*/
void t_town_prison_window::close_click( t_button *button_ptr )
{
	close();
}

